<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <!-- 模板内的表达式非常便利，但是设计它们的初衷是用于简单运算 -->
        <!-- 对于任何复杂逻辑，你都应当使用计算属性。 -->
        <p>翻转字符串：{{ reversedMessage }}</p>

        <!-- ------------------------ -->
        <!-- 计算属性缓存 vs method 方法 -->
        <!-- 在表达式中调用方法来达到与计算属性同样的效果： -->
        <p>翻转字符串：{{ reversedMesByMethod() }}</p>
        <!-- 不同的是计算属性是基于它们的响应式依赖进行缓存的 -->
        <!-- 只在相关响应式依赖（这里指message）发生改变时计算属性才会重新求值。这就意味着只要 message 还没有发生改变，多次访问 reversedMessage 计算属性会立即返回之前的计算结果，而不必再次执行函数。 -->
        <!-- 每当触发重新渲染时，调用方法将总会再次执行函数。而计算属性使用缓存 -->
        <!-- 如下，Date.now() 不是响应式依赖，意味着计算属性将不再更新，相比下，使用计算属性最佳 -->
        <p>{{ now }}</p>
        <!-- 若性能开销大的计算属性，若不希望有缓存，则用方法代替 -->

        <!-- -------------------------- -->
        <!-- 计算属性 vs 侦听属性 watch -->
        <!-- 很容易滥用 watch，通常更好的做法是使用计算属性而不是命令式的 watch 回调 -->
        <div>{{ fullName }}</div>

    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                message: 'hello',
                firstName: 'Foo',
                lastName: 'Bar',
                fullName: 'Foo Bar'
            },
            computed: {
                reversedMessage: function () {
                    return this.message.split('').reverse().join('')
                },
                now: function () {
                    return Date.now()
                },
                fullName: function () {
                    return this.firstName + ' ' + this.lastName
                },
                // 计算属性的 setter 
                // 计算属性默认只有 getter，不过在需要时你也可以提供一个 setter： 
                fullName: {
                    // getter
                    get: function () {
                        return this.firstName + ' ' + this.lastName
                    },
                    // setter
                    set: function (newValue) {
                        // 此代码将使得 运行 vm.fullName = 'John Doe' 时，setter 会被调用，vm.firstName 和 vm.lastName 也会相应地被更新。 
                        var names = newValue.split(' ')
                        this.firstName = names[0]
                        this.lastName = names[names.length - 1]
                    }
                }
            },
            methods: {
                reversedMesByMethod: function () {
                    return this.message.split('').reverse().join('')
                }
            },
            // watch: {
            //     firstName: function (val) {
            //         this.fullName = val + ' ' + this.lastName
            //     },
            //     lastName: function (val) {
            //         this.fullName = this.firstName + ' ' + val
            //     }
            // }
        })

    </script>
</body>

</html>